
/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "SampleCode.h"
#include "SkView.h"
#include "SkCanvas.h"
#include "SkGradientShader.h"
#include "SkGraphics.h"
#include "SkImageDecoder.h"
#include "SkImageEncoder.h"
#include "SkPath.h"
#include "SkRegion.h"
#include "SkShader.h"
#include "SkUtils.h"
#include "SkXfermode.h"
#include "SkColorPriv.h"
#include "SkColorFilter.h"
#include "SkTime.h"
#include "SkTypeface.h"

#include "SkStream.h"

static void make_image(SkBitmap* bm, SkBitmap::Config config, int configIndex)
    {
    const int   width = 98;
    const int   height = 100;
    SkBitmap    device;

    device.setConfig(SkBitmap::kARGB_8888_Config, width, height);
    device.allocPixels();

    SkCanvas    canvas(device);
    SkPaint     paint;

    paint.setAntiAlias(true);
    canvas.drawColor(SK_ColorRED);
    paint.setColor(SK_ColorBLUE);
    canvas.drawCircle(SkIntToScalar(width)/2, SkIntToScalar(height)/2,
                      SkIntToScalar(width)/2, paint);

    bm->setConfig(config, width, height);
    switch (config)
        {
        case SkBitmap::kARGB_8888_Config:
            bm->swap(device);
            break;
        case SkBitmap::kRGB_565_Config:
            {
            bm->allocPixels();
            for (int y = 0; y < height; y++)
                {
                for (int x = 0; x < width; x++)
                    {
                    *bm->getAddr16(x, y) = SkPixel32ToPixel16(*device.getAddr32(x, y));
                    }
                }
            break;
            }
        case SkBitmap::kIndex8_Config:
            {
            SkPMColor colors[256];
            for (int i = 0; i < 256; i++)
                {
                if (configIndex & 1)
                    {
                    colors[i] = SkPackARGB32(255-i, 0, 0, 255-i);
                    }
                else
                    {
                    colors[i] = SkPackARGB32(0xFF, i, 0, 255-i);
                    }
                }
            SkColorTable* ctable = new SkColorTable(colors, 256);
            bm->allocPixels(ctable);
            ctable->unref();

            for (int y = 0; y < height; y++)
                {
                for (int x = 0; x < width; x++)
                    {
                    *bm->getAddr8(x, y) = SkGetPackedR32(*device.getAddr32(x, y));
                    }
                }
            break;
            }
        default:
            break;
        }
    }

// configs to build the original bitmap in. Can be at most these 3
static const SkBitmap::Config gConfigs[] =
    {
    SkBitmap::kARGB_8888_Config,
    SkBitmap::kRGB_565_Config,
    SkBitmap::kIndex8_Config,   // opaque
    SkBitmap::kIndex8_Config    // alpha
    };

static const char* const gConfigLabels[] =
    {
    "8888", "565", "Index8",  "Index8 alpha"
    };

// types to encode into. Can be at most these 3. Must match up with gExt[]
static const SkImageEncoder::Type gTypes[] =
    {
    SkImageEncoder::kJPEG_Type,
    SkImageEncoder::kPNG_Type
    };

// must match up with gTypes[]
static const char* const gExt[] =
    {
    ".jpg", ".png"
    };

static const char* gPath = "/encoded/";

static void make_name(SkString* name, int config, int ext)
    {
    name->set(gPath);
    name->append(gConfigLabels[config]);
    name->append(gExt[ext]);
    }

#include <sys/stat.h>

class EncodeView : public SampleView
    {
    public:
        SkBitmap*   fBitmaps;
        size_t      fBitmapCount;

        EncodeView()
            {
#if 1
            (void)mkdir(gPath, S_IRWXU | S_IRWXG | S_IRWXO);

            fBitmapCount = SK_ARRAY_COUNT(gConfigs);
            fBitmaps = new SkBitmap[fBitmapCount];
            for (size_t i = 0; i < fBitmapCount; i++)
                {
                make_image(&fBitmaps[i], gConfigs[i], i);

                for (size_t j = 0; j < SK_ARRAY_COUNT(gExt); j++)
                    {
                    SkString path;
                    make_name(&path, i, j);

                    // remove any previous run of this file
                    remove(path.c_str());

                    SkImageEncoder* codec = SkImageEncoder::Create(gTypes[j]);
                    if (NULL == codec ||
                            !codec->encodeFile(path.c_str(), fBitmaps[i], 100))
                        {
                        SkDebugf("------ failed to encode %s\n", path.c_str());
                        remove(path.c_str());   // remove any partial file
                        }
                    delete codec;
                    }
                }
#else
            fBitmaps = NULL;
            fBitmapCount = 0;
#endif
            this->setBGColor(0xFFDDDDDD);
            }

        virtual ~EncodeView()
            {
            delete[] fBitmaps;
            }

    protected:
        // overrides from SkEventSink
        virtual bool onQuery(SkEvent* evt)
            {
            if (SampleCode::TitleQ(*evt))
                {
                SampleCode::TitleR(evt, "ImageEncoder");
                return true;
                }
            return this->INHERITED::onQuery(evt);
            }

        virtual void onDrawContent(SkCanvas* canvas)
            {
            if (fBitmapCount == 0)
                {
                return;
                }

            SkPaint paint;
            paint.setAntiAlias(true);
            paint.setTextAlign(SkPaint::kCenter_Align);

            canvas->translate(SkIntToScalar(10), SkIntToScalar(20));

            SkScalar x = 0, y = 0, maxX = 0;
            const int SPACER = 10;

            for (size_t i = 0; i < fBitmapCount; i++)
                {
                canvas->drawText(gConfigLabels[i], strlen(gConfigLabels[i]),
                                 x + SkIntToScalar(fBitmaps[i].width()) / 2, 0,
                                 paint);
                y = paint.getTextSize();

                canvas->drawBitmap(fBitmaps[i], x, y);

                SkScalar yy = y;
                for (size_t j = 0; j < SK_ARRAY_COUNT(gExt); j++)
                    {
                    yy += SkIntToScalar(fBitmaps[i].height() + 10);

                    SkBitmap bm;
                    SkString name;

                    make_name(&name, i, j);

                    SkImageDecoder::DecodeFile(name.c_str(), &bm);
                    canvas->drawBitmap(bm, x, yy);
                    }

                x += SkIntToScalar(fBitmaps[i].width() + SPACER);
                if (x > maxX)
                    {
                    maxX = x;
                    }
                }

            y = (paint.getTextSize() + SkIntToScalar(fBitmaps[0].height())) * 3 / 2;
            x = maxX + SkIntToScalar(10);
            paint.setTextAlign(SkPaint::kLeft_Align);

            for (size_t j = 0; j < SK_ARRAY_COUNT(gExt); j++)
                {
                canvas->drawText(gExt[j], strlen(gExt[j]), x, y, paint);
                y += SkIntToScalar(fBitmaps[0].height() + SPACER);
                }
            }

        virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y)
            {
            this->inval(NULL);
            return this->INHERITED::onFindClickHandler(x, y);
            }

    private:
        typedef SampleView INHERITED;
    };

//////////////////////////////////////////////////////////////////////////////

static SkView* MyFactory()
    {
    return new EncodeView;
    }
static SkViewRegister reg(MyFactory);

